#define _CRT_SECURE_NO_WARNINGS
#include"CleanMine.h"



void InitFaceTable(char Table[ROW][COL])//初始化玩家的桌面
{
	memset(Table, '+', ROW * COL * sizeof(char));
}

void InitInsideTable(char Table[ROW][COL], int mine_num)//初始化后台桌面
{
	int rand_row;
	int rand_col;
	

	srand((unsigned int)time(NULL));

	while (mine_num)
	{
		rand_row = rand() % ROW ;
		rand_col = rand() % COL ;

		if (Table[rand_row][rand_col] != '*')
		{
			Table[rand_row][rand_col] = '*';
		}
		else
			continue;

		mine_num--;	
	} 
	//其他非雷位置显示自己周围雷的数量
	UpdateInsideTable(Table);

}

//更新内置棋盘，将非雷位置的数字更新
void UpdateInsideTable(char Table[ROW][COL])
{
	int i;
	int j;

	for (i = 0; i < ROW; i++)
		for (j = 0; j < COL; j++)
		{
			if ('*' != Table[i][j])
			{
				Table[i][j] = account_sign_num(Table,'*', i, j) + 48;
			}
		}
}

void ShowTable(char Table[ROW][COL])//打印桌面
{
	int row;
	int col;
	int i = 0;

	printf("现在为您显示棋盘...\n");

	printf("  ");//雷盘第一行输出对应列标和格式
	for (i = 0; i < COL; i++)
	{
		printf("   %d", i);
	}
	printf("\n");
	printf("__");
	for (i = 0; i < COL; i++)
	{
		printf("____");
	}
	printf("\n");


	for (row = 0; row < ROW; row++)
	{
		printf("%d|", row);//第一列输出对应行标和格式
		for (col = 0; col < COL; col++)
		{	
			printf("%4c", Table[row][col]);
		}
		printf("\n");
		printf(" |\n");
	}
}

int  account_sign_num(char Table[ROW][COL],char sign,int row, int col)//统计周围雷的数量
{
	int count = 0;
	int i;

	//分上、中、下三次统计
	//i=-1,使其递增可以表示上中三或者左中右三个行或列
	i = -1;
	while (i < 2)
	{
		if ((row - 1 < 0) || (col + i > COL - 1 || col + i < 0))
		{
			i++;
			continue;
		}
			
		else if (sign == Table[row - 1][col + i])
			count++;
		
		i++;
	}

	i = -1;
	while (i < 2)
	{
		if ((col + i < 0) || (col + i > COL - 1))
		{
			i++;
			continue;
		}
			
		else if (sign == Table[row][col + i])
		    count++;

		i++;
	}

	i = -1;
	while (i < 2)
	{
		if ((row + 1 > ROW) || (col + i < 0) || (col + i > COL - 1))
		{
			i++;
			continue;
		}
		else if (sign == Table[row + 1][col + i])
			count++;

		i++;	
	}

	return count;
}

int Is_Die(char Table[ROW][COL],int row, int col)//判断是否死亡
{
	if ('*' == Table[row][col])
	{
		printf("瓜娃子，你炸咧...\n");
		return 1;
	}
	else
		return 0;
}

void FirstNotDie(char Table[ROW][COL], int row,int col)//扩展功能:让第一次踩雷不死，并在其他位置生成雷,在220-223行
{
	int mine_row;
	int	mine_col;

	if (Table[row][col] == '*')
	{
		Table[row][col] = account_sign_num(Table,'*', row, col) + 48;//该位置为雷，计算周围雷的数量，重新赋值
		do
		{
			mine_row = rand() % ROW;
			mine_col = rand() % COL;
		} while (Table[mine_row][mine_col] == '*');
		Table[mine_row][mine_col] = '*';//将不是雷的随机位置变为雷
		UpdateInsideTable(Table);
	}
}

//当前位置周围9宫格没有雷，向周围扩展显示，遇到雷数量大于0的位置停止
void ExpandAround(char BackTable[ROW][COL], char PlayerTable[ROW][COL], int row, int col)
{
	int expand_time = 0;
	int i;
	

	expand_time = account_sign_num(BackTable, '0', row, col);
	while (expand_time)
	{
		//分上、中、下三次统计
		//i=-1,使其递增可以表示上中三或者左中右三个行或列
		i = -1;
		while (i < 2)
		{
			//超出棋盘范围，则进行下次循环
			if ((row - 1 < 0) || (col + i > COL - 1 || col + i < 0))
			{
				i++;
				continue;
			}
			//该位置是'+'，标识该位置还没被使用过，继续向下；是'0'，标识周围没有雷，继续递归
			else if ('+' == PlayerTable[row - 1][col + i])
			{
				if ('0' == BackTable[row - 1][col + i])
				{
					PlayerTable[row - 1][col + i] = BackTable[row - 1][col + i];
					ExpandAround(BackTable, PlayerTable, row - 1, col + i);
				}
				else
				{
					PlayerTable[row - 1][col + i] = BackTable[row - 1][col + i];		
				}
			}
			i++;	
		}
		//判断当前行，三个位置是否需要扩展
		i = -1;
		while (i < 2)
		{
			if ((col + i < 0) || (col + i > COL - 1))
			{
				i++;
				continue;
			}
			else if ('+' == PlayerTable[row][col + i])
			{
				if ('0' == BackTable[row][col + i])
				{
					PlayerTable[row][col + i] = BackTable[row][col + i];
					ExpandAround(BackTable, PlayerTable, row , col + i);
				}
				else
				{
					PlayerTable[row][col + i] = BackTable[row][col + i];
				}
			}
			i++;
		}
		//判断下一行，三个位置是否需要扩展
		i = -1;
		while (i < 2)
		{
			if ((row + 1 > ROW) || (col + i < 0) || (col + i > COL - 1))
			{
				i++;
				continue;
			}
			else if ('+' == PlayerTable[row + 1][col + i])
			{
				if ('0' == BackTable[row + 1][col + i])
				{
					PlayerTable[row + 1][col + i] = BackTable[row + 1][col + i];
					ExpandAround(BackTable, PlayerTable, row + 1, col + i);
				}
				else
				{
					PlayerTable[row + 1][col + i] = BackTable[row + 1][col + i];
				}
			}
			i++;
		}
		expand_time--;	
	}
}

int Is_Win(char NowTable[ROW][COL])//判赢实现
{
	int i;
	int j;
	int count = 0;

	for(i = 0; i< ROW; i++)
		for (j = 0; j < COL; j++)
		{
			if ('+' == NowTable[i][j])
				count++;
			else
				continue;
		}
	return count;
}

void PlayGame()//游戏功能实现核心
{
	char InsideTable[ROW
	][COL];
	char FaceTable[ROW][COL];
	int mine_num = 5;//雷的数量，建议赋值不要大于行列之积的一半的大小
	int click_time = ROW*COL - mine_num;
	int player_row;
	int player_col;

	InitInsideTable(InsideTable,mine_num);//初始化两个雷盘
	InitFaceTable(FaceTable);
	//ShowTable(InsideTable);//初始打印雷盘，默认不显示
	ShowTable(FaceTable);

	while (Is_Win(FaceTable)!=mine_num)//判断输赢
	{
		printf("输入你选择的坐标...\n");

		scanf("%d%d", &player_row, &player_col);
		if (player_row >= 0 && player_col >= 0 && player_row < ROW && player_col < COL)
		{
			if (click_time == ROW*COL - mine_num)//第一次踩雷不死
			{
				FirstNotDie(InsideTable, player_row, player_col);
			}

			if (Is_Die(InsideTable, player_row, player_col))//如果当前位置是雷，展示并跳出循环
			{
				ShowTable(InsideTable);
				break;
			}
			else
			{
				if (InsideTable[player_row][player_col] == '0')
				{
					ExpandAround(InsideTable, FaceTable, player_row, player_col);
					ShowTable(FaceTable);
				}
				else
				{
					FaceTable[player_row][player_col] = InsideTable[player_row][player_col];
					ShowTable(FaceTable);			
				}
				click_time--;
			}
		}
		else
			printf("输入有误，请重新输入...");
	}

	if (Is_Win(FaceTable) == mine_num)
	{
		printf("恭喜你排雷成功...\n");
		ShowTable(FaceTable);
	}
		

}
